 /***
     Amrita ITEWS - Copyright (C) 2009 Amrita Vishwa Vidyapeetham, Amritapuri.
                                        (http://www.amrita.edu)
     ***************************************************************************
     This file is part of the Amrita ITEWS distribution.
     Amrita ITEWS is free software; you can redistribute it and/or modify it
     under the terms of the GNU General Public License (version 2) as published
     by the Free Software Foundation AND MODIFIED BY the Amrita ITEWS exception.
     ***NOTE*** The exception to the GPL is included to allow you to distribute
     a combined work that includes Amrita ITEWS without being obliged to provide
     the source code for proprietary components outside of the Amrita ITEWS
     software. Amrita ITEWS is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
     Public License for more details. You should have received a copy of the GNU
     General Public License and the Amrita ITEWS license exception along with
     Amrita ITEWS if not then it can be viewed here:
     http://itews.amrita.ac.in/license.html.

     Note: This software is closely coupled to FreeRTOS and hence the
     licensing terms of FreeRTOS would apply.


     Documentation, latest information, license and contact details are at:
     http://itews.amrita.ac.in/


     Amrita ITEWS source code can be found at:
     http://code.google.com/p/itews


     The initial code-base of Amrita ITEWS was developed by Amrita Vishwa
     Vidyapeetham as part of the project titled,"Intelligent & Interactive
     Telematics using Emerging Wireless Technologies for Transport Systems
     (ITEWS)" sponsored by Technology Information Forecasting and Assessment
     Council (TIFAC), India.
 ***/


#include <mutex_api.h>
#include <FreeRTOS.h>
#include <task.h>
#include <queue.h>
#include <mutex_api.h>
#include <errno.h>


#define MUTEX_MAX		20

#define MUTEX_FREE		0
#define MUTEX_ALLOC		1
#define MUTEX_LOCKED 	2

typedef struct
{
	uint8				state;
	wait_list_t			wl;//wait list for tasks to block on mutex
}mutex_ctx_t;

#define MUTEX_CTX(p) ((mutex_ctx_t*)(p))
mutex_ctx_t mutexes[MUTEX_MAX];

STATUS mutex_create	( HMUTEX *h )
{
	int i;
	int max;

	max = MUTEX_MAX;

	taskENTER_CRITICAL();
	{
		for(i=0;i<MUTEX_MAX;i++)
		{
			if(MUTEX_FREE == mutexes[i].state)
			{
				mutexes[i].state = MUTEX_ALLOC;
				task_wait_list_init(&mutexes[i].wl);
				break;
			}
		}
	}
	taskEXIT_CRITICAL();

	if(i < MUTEX_MAX)
	{
		h->mutex_ctx = &mutexes[i];
		return 0;
	}
	return -ENOBUFS;
}

STATUS mutex_lock	( HMUTEX h )
{
	uint8 prev_state;
	int32 status=0;

	taskENTER_CRITICAL();
	{
		prev_state = MUTEX_CTX(h.mutex_ctx)->state;
		MUTEX_CTX(h.mutex_ctx)->state|= MUTEX_LOCKED;
		if(prev_state&MUTEX_LOCKED)
		{
			task_wait_list_enqueue_(&(MUTEX_CTX(h.mutex_ctx)->wl), CURR_WAIT_STRUCT());
		}
	}
	taskEXIT_CRITICAL();

	if(prev_state&MUTEX_LOCKED)
	{
		TASK_WAIT(CURR_WAIT_STRUCT(), &status);
	}
	return status;
}

STATUS mutex_unlock	( HMUTEX h )
{
	wait_struct_t *w=(wait_struct_t*)0UL;
	int32 status=0;

	taskENTER_CRITICAL();
	{
		if(TASK_WAIT_LIST_IS_EMPTY(&(MUTEX_CTX(h.mutex_ctx)->wl)))
		{
			MUTEX_CTX(h.mutex_ctx)->state&= ~MUTEX_LOCKED;
		}else
		{
			w = task_wait_list_dequeue_(&(MUTEX_CTX(h.mutex_ctx)->wl));
		}
	}
	taskEXIT_CRITICAL();

	if(w)
	{
		TASK_NOTIFY(w, &status);
	}
	return 0;
}

STATUS mutex_destroy(HMUTEX h )
{
	//TODO
	return 0;
}

